package com.huahua.api.util;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.huahua.api.entity.base.QiNiuOssUploadBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * QR码生成工具类（支持Logo）
 *
 * @author Huahua-Ai
 * @date 2025-08-23 15:00:00
 * @description QR码生成工具，支持添加自定义Logo和上传到七牛云
 */
@Component
@Slf4j
public class QRCodeWithLogoUtil {

    @Autowired
    private QiNiuUtils qiNiuUtils;

    /**
     * 生成带Logo的QR码并上传到七牛云
     *
     * @param qrText            QR码内容
     * @param width             QR码宽度
     * @param height            QR码高度
     * @param logoUrl           Logo的URL地址（公网可访问）
     * @param logoWidth         Logo宽度
     * @param logoHeight        Logo高度
     * @param objectName        上传到七牛云的文件名（不含扩展名）
     * @param removeWhiteBorder 是否去除白边
     * @return 上传成功后的URL
     */
    public String generateQrCodeWithLogoAndUpload(String qrText, int width, int height,
                                                  String logoUrl, int logoWidth, int logoHeight,
                                                  String objectName, boolean removeWhiteBorder) {
        try {
            // 生成QR码
            BufferedImage qrImage = generateQRCodeImage(qrText, width, height, removeWhiteBorder);

            // 添加Logo（如果提供了Logo URL）
            BufferedImage finalImage = qrImage;
            if (logoUrl != null && !logoUrl.isEmpty()) {
                BufferedImage logoImage = loadLogoFromUrl(logoUrl);
                if (logoImage != null) {
                    finalImage = addLogoToQrCode(qrImage, logoImage, logoWidth, logoHeight);
                }
            }

            // 将图片转换为字节数组
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(finalImage, "PNG", baos);
            byte[] imageBytes = baos.toByteArray();

            // 上传到七牛云
            ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
            QiNiuOssUploadBean uploadResult = qiNiuUtils.uploadFileByStream(inputStream, objectName, "png");

            if (uploadResult != null && uploadResult.getUrl() != null) {
                log.info("QR码生成并上传成功: {}", uploadResult.getUrl());
                return uploadResult.getUrl();
            } else {
                log.error("QR码上传失败");
                throw new RuntimeException("QR码上传到七牛云失败");
            }

        } catch (Exception e) {
            log.error("生成QR码失败", e);
            throw new RuntimeException("生成QR码失败: " + e.getMessage(), e);
        }
    }

    /**
     * 生成不带Logo的QR码并上传
     */
    public String generateQrCodeAndUpload(String qrText, int width, int height, String objectName, boolean removeWhiteBorder) {
        return generateQrCodeWithLogoAndUpload(qrText, width, height, null, 0, 0, objectName, removeWhiteBorder);
    }

    /**
     * 生成QR码图片（不含Logo）
     */
    private BufferedImage generateQRCodeImage(String text, int width, int height, boolean removeWhiteBorder) throws WriterException {
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.MARGIN, 0);

        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height, hints);

        // 根据参数决定是否删除白边
        if (removeWhiteBorder) {
            return deleteWhiteBorder(bitMatrix, width, height);
        } else {
            return MatrixToImageWriter.toBufferedImage(bitMatrix);
        }
    }

    /**
     * 删除QR码的白边
     */
    private BufferedImage deleteWhiteBorder(BitMatrix matrix, int qrWidth, int qrHeight) {
        int[] rec = matrix.getEnclosingRectangle();
        if (rec == null) {
            return MatrixToImageWriter.toBufferedImage(matrix);
        }

        int resWidth = rec[2];
        int resHeight = rec[3];

        BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
        resMatrix.clear();
        for (int i = 0; i < resWidth; i++) {
            for (int j = 0; j < resHeight; j++) {
                if (matrix.get(i + rec[0], j + rec[1])) {
                    resMatrix.set(i, j);
                }
            }
        }

        BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(resMatrix);

        // 如果QR码的实际宽高和预期的宽高不一致，则缩放
        if (qrWidth != resWidth || qrHeight != resHeight) {
            BufferedImage tmp = new BufferedImage(qrWidth, qrHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics = tmp.createGraphics();
            graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            graphics.drawImage(bufferedImage.getScaledInstance(qrWidth, qrHeight, Image.SCALE_SMOOTH), 0, 0, null);
            graphics.dispose();
            bufferedImage = tmp;
        }

        return bufferedImage;
    }

    /**
     * 添加Logo到QR码中心
     */
    private BufferedImage addLogoToQrCode(BufferedImage qrCodeImage, BufferedImage logoImage,
                                          int logoWidth, int logoHeight) {
        Graphics2D graphics = qrCodeImage.createGraphics();

        // 计算Logo位置（居中）
        int x = (qrCodeImage.getWidth() - logoWidth) / 2;
        int y = (qrCodeImage.getHeight() - logoHeight) / 2;

        // 设置抗锯齿
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

        // 绘制白色背景（可选，用于Logo的清晰度）
        int padding = 2;
        graphics.setColor(Color.WHITE);
        graphics.fillRect(x - padding, y - padding, logoWidth + padding * 2, logoHeight + padding * 2);

        // 绘制Logo
        graphics.drawImage(logoImage, x, y, logoWidth, logoHeight, null);

        // 释放资源
        graphics.dispose();

        return qrCodeImage;
    }

    /**
     * 从URL加载Logo图片
     */
    private BufferedImage loadLogoFromUrl(String logoUrl) {
        try {
            URL url = new URL(logoUrl);
            BufferedImage logoImage = ImageIO.read(url);
            if (logoImage == null) {
                log.warn("无法从URL加载Logo图片: {}", logoUrl);
                return null;
            }
            return logoImage;
        } catch (Exception e) {
            log.warn("加载Logo图片失败: {}", logoUrl, e);
            return null;
        }
    }

    /**
     * 生成带Logo的QR码（使用默认尺寸）
     */
    public String generateQrCodeWithLogo(String qrText, String logoUrl, String objectName, boolean removeWhiteBorder) {
        // 默认尺寸
        int qrSize = 300;
        int logoSize = qrSize / 5; // Logo占QR码的1/5

        return generateQrCodeWithLogoAndUpload(qrText, qrSize, qrSize,
                logoUrl, logoSize, logoSize,
                objectName, removeWhiteBorder);
    }

    /**
     * 生成QR码本地图片（用于测试）
     */
    public BufferedImage generateQrCodeImage(String qrText, int width, int height,
                                             String logoUrl, int logoWidth, int logoHeight, boolean removeWhiteBorder) {
        try {
            BufferedImage qrImage = generateQRCodeImage(qrText, width, height, removeWhiteBorder);

            if (logoUrl != null && !logoUrl.isEmpty()) {
                BufferedImage logoImage = loadLogoFromUrl(logoUrl);
                if (logoImage != null) {
                    return addLogoToQrCode(qrImage, logoImage, logoWidth, logoHeight);
                }
            }

            return qrImage;
        } catch (Exception e) {
            log.error("生成QR码图片失败", e);
            throw new RuntimeException("生成QR码图片失败: " + e.getMessage(), e);
        }
    }
}
